<?php
/**
* pdflib wrapper
* Copyright (C) 2009 Noor Griffin
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
* 
* Contact: noorg1977@gmail.com
*/
class pdfwrapper
{
	/**
	 * The path and name of the pdf
	 * 
	 * @var string
	 */
	private $file_name;
	
	/**
	 * The page width of the pdf
	 * 
	 * @var int
	 */
	private $page_width;
	
	/**
	 * The page height of the pdf
	 * 
	 * @var int
	 */
	private $page_height;
	
	/**
	 * The page lower left most horizontal position
	 * 
	 * @var int
	 */
	private $lowerleft_x;
	
	/**
	 * The page lower left most verticle position
	 * 
	 * @var int
	 */
	private $lowerleft_y;
	
	/**
	 * The page upper right most horizontal position
	 * 
	 * @var int
	 */
	private $upperright_x;
	
	/**
	 * The page upper right most verticle position
	 * 
	 * @var int
	 */
	private $upperright_y;
	
	/**
	 * The page orientation of the pdf
	 * 
	 * @var string
	 */
	private $orientation;
	
	/**
	 * The font size used in the pdf
	 * 
	 * @var int
	 */
	private $font_size;
	
	/**
	 * The font name for normal weighted font used in the pdf
	 * 
	 * @var string
	 */
	private $normal_font;
	
	/**
	 * The font name for bold weighted font used in the pdf
	 * 
	 * @var string
	 */
	private $bold_font;
	
	/**
	 * The spacing size between lines in the pdf
	 * 
	 * @var int
	 */
	private $line_spacing;
	
	/**
	 * The search path for other files needed in the pdf
	 * 
	 * @var string
	 */
	private $search_path;
	
	/**
	 * Table options for tables created
	 * 
	 * @var string
	 */
	private $table_options;
	
	/**
	 * The reference number returned when setting the normal font
	 * 
	 * @var int
	 */
	private $normal_font_number;
	
	/**
	 * The reference number returned when setting the bold font
	 * 
	 * @var int
	 */
	private $bold_font_number;
	
	/**
	 * The table data alignment
	 * 
	 * @var string
	 */
	private $td_align;
	
	/**
	 * The pdf reference
	 * 
	 * @var object
	 */
	private $pdf;
	
	/**
	 * The pdf wrapper constructor
	 * 
	 * @param array configurations
	 * @param string filepath/filename of the pdf to be created
	 * @return void
	 */
	public function __construct($configs, $file_name)
	{
		// Set the filename
		$this->setFileName($file_name);
		
		// Set the page width
		$this->setPageWidth($configs['page_width']);
		
		// Set the page height
		$this->setPageHeight($configs['page_height']);
		
		// Set the lower left x position
		$this->setLowerLeftX($configs['lowerleft_x']);
		
		// Set the lower left y position
		$this->setLowerLeftY($configs['lowerleft_y']);
		
		// Set the upper right x position
		$this->setUpperRightX($configs['upperright_x']);
		
		// Set the upper right y position
		$this->setUpperRightY($configs['upperright_y']);
		
		// Set the page orientation
		$this->setPageOrientation($configs['page_orientation']);
		
		// Set the font size
		$this->setFontSize($configs['font_size']);
		
		// Set a normal weighted font
		$this->setNormalFont($configs['normal_font']);
		
		// Set a bold weighted font
		$this->setBoldFont($configs['bold_font']);
		
		// Set the line spacing
		$this->setLineSpacing($configs['line_spacing']);
		
		// Set a search path for other needed files
		$this->setSearchPath($configs['search_path']);
		
		// Set the file author
		$this->setAuthor($configs['author']);
		
		// Set the page title
		$this->setTitle($configs['title']);
		
		// Set default alignment for tables
		$this->setTableAlignment($configs['td_align']);
		
		// Set default cell margin size
		$this->setTableDataMargin($configs['td_margin']);
		
		// Create the pdf object an initialize
		$this->setObj(new PDFlib());
		
		// Set the error policy to return (stop)
		$this->getObj()->set_parameter('errorpolicy', 'return');
		
		// Set the search path for needed files
		$this->getObj()->set_parameter(
			'SearchPath', $this->getSearchPath()
		);
		
		// Start the document
		if ($this->getObj()->begin_document($this->getFileName(), '')
			 == 0
		)
		{
			die("Error: " . $this->getObj()->get_errmsg());
		}
		
		// Set the file author
		$this->getObj()->set_info('Author', $this->getAuthor());
		
		// Set the page title
		$this->getObj()->set_info('Title', $this->getTitle());
		
		// Load the fonts
		$normal_font = $this->getObj()->load_font(
			$this->getNormalFont(), 'winansi', ''
		);
		$bold_font = $this->getObj()->load_font(
			$this->getBoldFont(), 'winansi', ''
		);
		
		// If the Font fails, try to load a different one
		if ($bold_font == 0)
		{
			$bold_font = $this->getObj()->load_font(
				'Arial Bold', 'winansi', ''
			);
		}
		
		// Check for font errors
		if ($normal_font == 0 or $bold_font == 0)
		{
			die('Error: ' . $this->getObj()->get_errmsg());
		}

		// Capture the font numbers returned when setting the fonts
		$this->setNormalFontNumber($normal_font);
		$this->setBoldFontNumber($bold_font);
		
		// Set the table options
		$this->setTableOptions();
	}
	
	/**
	 * Sets the filename for the pdf
	 * 
	 * @param string filename
	 * @return void
	 */
	private function setFileName($file_name)
	{
		$this->file_name = $file_name;
	}
	
	/**
	 * Gets the filename for the pdf
	 * 
	 * @return string
	 */
	private function getFileName()
	{
		if (!isset($this->file_name))
		{
			return NULL;
		}
		return $this->file_name;
	}
	
	/**
	 * Sets the page width for the pdf
	 * 
	 * @param int width
	 * @return void
	 */
	private function setPageWidth($width)
	{
		$this->page_width = $width;
	}
	
	/**
	 * Gets the page width for the pdf
	 * 
	 * @return int
	 */
	private function getPageWidth()
	{
		if (!isset($this->page_width))
		{
			return 0;
		}
		return $this->page_width;
	}
	
	/**
	 * Sets the page height for the pdf
	 * 
	 * @param int page height
	 * @return void
	 */
	private function setPageHeight($height)
	{
		$this->page_height = $height;
	}
	
	/**
	 * Gets the page height for the pdf
	 * 
	 * @return int
	 */
	private function getPageHeight()
	{
		if (!isset($this->page_height))
		{
			return 0;
		}
		return $this->page_height;
	}
	
	/**
	 * Sets the page lower left most horizontal position
	 * 
	 * @param int page llx
	 * @return void
	 */
	private function setLowerLeftX($llx)
	{
		$this->lowerleft_x = $llx;
	}
	
	/**
	 * Gets the page lower left most horizontal position
	 * 
	 * @return int
	 */
	private function getLowerLeftX()
	{
		if (!isset($this->lowerleft_x))
		{
			return 0;
		}
		return $this->lowerleft_x;
	}
	
	/**
	 * Sets the page lower left most verticle position
	 * 
	 * @param int page lly
	 * @return void
	 */
	private function setLowerLeftY($lly)
	{
		$this->lowerleft_y = $lly;
	}
	
	/**
	 * Gets the page lower left most verticle position
	 * 
	 * @return int
	 */
	private function getLowerLeftY()
	{
		if (!isset($this->lowerleft_y))
		{
			return 0;
		}
		return $this->lowerleft_y;
	}
	
	/**
	 * Sets the page upper right most horizontal position
	 * 
	 * @param int page urx
	 * @return void
	 */
	private function setUpperRightX($urx)
	{
		$this->upperright_x = $urx;
	}
	
	/**
	 * Gets the page upper right most horizontal position
	 * 
	 * @return int
	 */
	private function getUpperRightX()
	{
		if (!isset($this->upperright_x))
		{
			return 0;
		}
		return $this->upperright_x;
	}
	
	/**
	 * Sets the page upper right most verticle position
	 * 
	 * @param int page ury
	 * @return void
	 */
	private function setUpperRightY($ury)
	{
		$this->upperright_y = $ury;
	}
	
	/**
	 * Gets the page upper right most verticle position
	 * 
	 * @return int
	 */
	private function getUpperRightY()
	{
		if (!isset($this->upperright_y))
		{
			return 0;
		}
		return $this->upperright_y;
	}
	
	/**
	 * Sets the page orientation for the pdf
	 * 
	 * @param string orientation (topdown or other)
	 * @return void
	 */
	private function setPageOrientation($orientation)
	{
		$this->orientation = $orientation;
	}
	
	/**
	 * Gets the page orientation for the pdf
	 * 
	 * @return string
	 */
	private function getPageOrientation()
	{
		if (!isset($this->orientation))
		{
			return NULL;
		}
		return $this->orientation;
	}
	
	/**
	 * Sets the font size for the pdf
	 * 
	 * @param int font size
	 * @return void
	 */
	private function setFontSize($font_size)
	{
		$this->font_size = $font_size;
	}
	
	/**
	 * Gets the font size for the pdf
	 * 
	 * @return int
	 */
	private function getFontSize()
	{
		if (!isset($this->font_size))
		{
			return 0;
		}
		return $this->font_size;
	}
	
	/**
	 * Sets the normal-weighted font for the pdf
	 * 
	 * @param string font name
	 * @return void
	 */
	private function setNormalFont($normal_font)
	{
		$this->normal_font = $normal_font;
	}
	
	/**
	 * Gets the normal-weighted font for the pdf
	 * 
	 * @return string
	 */
	private function getNormalFont()
	{
		if (!isset($this->normal_font))
		{
			return NULL;
		}
		return $this->normal_font;
	}
	
	/**
	 * Sets the bold-weighted font for the pdf
	 * 
	 * @param string font name
	 * @return void
	 */
	private function setBoldFont($bold_font)
	{
		$this->bold_font = $bold_font;
	}
	
	/**
	 * Gets the bold-weighted font for the pdf
	 * 
	 * @return string
	 */
	private function getBoldFont()
	{
		if (!isset($this->bold_font))
		{
			return NULL;
		}
		return $this->bold_font;
	}
	
	/**
	 * Sets the spacing between lines in the pdf
	 * 
	 * @param int line spacing
	 * @return void
	 */
	private function setLineSpacing($line_spacing)
	{
		$this->line_spacing = $line_spacing;
	}
	
	/**
	 * Gets the spacing between lines in the pdf
	 * 
	 * @return int
	 */
	private function getLineSpacing()
	{
		if (!isset($this->line_spacing))
		{
			return 0;
		}
		return $this->line_spacing;
	}
	
	/**
	 * Sets the search path for the pdf
	 * 
	 * @param string path
	 * @return void
	 */
	private function setSearchPath($search_path)
	{
		$this->search_path = $search_path;
	}
	
	/**
	 * Gets the search path for the pdf
	 * 
	 * @return string
	 */
	private function getSearchPath()
	{
		if (!isset($this->search_path))
		{
			return NULL;
		}
		return $this->search_path;
	}
	
	/**
	 * Sets the author for the pdf
	 * 
	 * @param string author name
	 * @return void
	 */
	private function setAuthor($author)
	{
		$this->author = $author;
	}
	
	/**
	 * Gets the author name for the pdf
	 * 
	 * @return string
	 */
	private function getAuthor()
	{
		if (!isset($this->author))
		{
			return NULL;
		}
		return $this->author;
	}
	
	/**
	 * Sets the page title for the pdf
	 * 
	 * @param string title
	 * @return void
	 */
	private function setTitle($title)
	{
		$this->title = $title;
	}
	
	/**
	 * Gets the page title for the pdf
	 * 
	 * @return string
	 */
	private function getTitle()
	{
		if (!isset($this->title))
		{
			return NULL;
		}
		return $this->title;
	}
	
	/**
	 * Sets the table data text alignment
	 * 
	 * @param string alignment
	 * @return void
	 */
	private function setTableAlignment($align)
	{
		$this->td_align = $align;
	}
	
	/**
	 * Gets the table data text alignment
	 * 
	 * @return string
	 */
	private function getTableAlignment()
	{
		if (!isset($this->td_align))
		{
			return '';
		}
		return $this->td_align;
	}
	
	/**
	 * Sets the table data cell margins
	 * 
	 * @param int margin
	 * @return void
	 */
	private function setTableDataMargin($margin)
	{
		$this->td_margin = $margin;
	}
	
	/**
	 * Gets the table data cell margins
	 * 
	 * @return int
	 */
	private function getTableDataMargin()
	{
		if (!isset($this->td_margin))
		{
			return 0;
		}
		return $this->td_margin;
	}
	
	/**
	 * Sets the normal font reference number for normal fonts created
	 * 
	 * @param int reference number
	 * @return void
	 */
	private function setNormalFontNumber($number)
	{
		$this->normal_font_number = $number;
	}
	
	/**
	 * Gets the normal font reference number for normal fonts created
	 * 
	 * @param int reference number
	 * @return void
	 */
	private function getNormalFontNumber()
	{
		if (!isset($this->normal_font_number))
		{
			return 0;
		}
		return $this->normal_font_number;
	}
	
	/**
	 * Sets the bold font reference number for bold fonts created
	 * 
	 * @param int reference number
	 * @return void
	 */
	private function setBoldFontNumber($number)
	{
		$this->bold_font_number = $number;
	}
	
	/**
	 * Gets the bold font reference number for bold fonts created
	 * 
	 * @param int reference number
	 * @return void
	 */
	private function getBoldFontNumber()
	{
		if (!isset($this->bold_font_number))
		{
			return 0;
		}
		return $this->bold_font_number;
	}
	
	/**
	 * Instantiates the pdf object and initializes it
	 * 
	 * @param obj pdf
	 * @return void
	 */
	private function setObj($pdf_obj)
	{
		$this->pdf = $pdf_obj;
	}
	
	/**
	 * Gets the pdf object
	 * 
	 * @return object
	 */
	public function getObj()
	{
		if (!isset($this->pdf))
		{
			return NULL;
		}
		return $this->pdf;
	}
	
	/**
	 * Sets table options for a table cells not to be created
	 * 
	 * @return void
	 */
	private function setTableOptions()
	{
		$this->table_options = 'fittextline={font=' 
			. $this->getNormalFontNumber() . ' fontsize=' 
			. $this->getFontSize() . ' position={' 
			. $this->getTableAlignment() . ' center}} margin=' 
			. $this->getTableDataMargin() . '';
	}
	
	/**
	 * Gets table reference collection
	 * 
	 * @return array
	 */
	private function getTableOptions()
	{
		if (!isset($this->table_options))
		{
			return '';
		}
		return $this->table_options;
	}
	
	/**
	 * Adds table data to the row/cell for a specified table ref number
	 * 
	 * @param string table data
	 * @param int row
	 * @param int col
	 * @param int table reference number
	 * @return int
	 */
	public function addTableCell($tbl_ref, $col, $row, $td)
	{
		$ret = $this->getObj()->add_table_cell(
			$tbl_ref, 
			$col, 
			$row, 
			$td, 
			$this->getTableOptions()
		);
		return $ret;
	}
	
	/**
	* Returns the RGB values for a given hex string
	* 
	* @param string hexidecimal color code
	* @return array
	*/
	private function getRGBFromHex($hexcolor)
	{
		$color['r'] = hexdec(substr($hexcolor, 0, 2))/255;
		$color['g'] = hexdec(substr($hexcolor, 2, 2))/255;
		$color['b'] = hexdec(substr($hexcolor, 4, 2))/255;
		
		if ($color['r'] == 0) $color['r'] = 0.0;
		if ($color['g'] == 0) $color['g'] = 0.0;
		if ($color['b'] == 0) $color['b'] = 0.0;
		
		return array($color['r'], $color['g'], $color['b']);
	}
	
	/**
	 * Creates a table out of an array of data for the PDF
	 * 
	 * @param object pdf
	 * @param array data (only two dimensional array will work)
	 * @return void
	 */
	public function createDataTable($pdf_obj, $data_array)
	{
		$t2 = 0;
		foreach ($data_array as $data)
		{
			$headers = array_keys($data);
			$tds_array[] = array_values($data);
		}

		$row = $col = 1;
		foreach ($headers as $header)
		{
			$t2 = $this->addTableCell($t2, $col, $row, $header);
			if ($t2 == 0)
			{
				die("Error: " . $pdf_obj->get_errmsg());
			}
			$col++;
		}
		$row++;

		foreach ($tds_array as $tds)
		{
			$col = 1;
			foreach ($tds as $td)
			{
				$t2 = $this->addTableCell($t2, $col, $row, $td);
				if ($t2 == 0)
				{
					die("Error: " . $pdf_obj->get_errmsg());
				}
				$col++;
			}
			$row++;
		}
		$this->closeTable($t2);
	}
	
	/**
	 * Closes out a table by looping through all added table cells and
	 * making room in the document for each, with labels and automatic
	 * pagination
	 * 
	 * @param table reference number
	 * @return void
	 */
	private function closeTable($table_ref)
	{
		$page = 1;
		$optlist = 'showgrid=false';
		do {
			$this->getObj()->begin_page_ext(
				0, 0, 'width=a4.width height=a4.height'
			);

			// Add the document title to each page added
			$this->getObj()->setfont(
				$this->getBoldFontNumber(), $this->getFontSize()
			);
			$this->getObj()->show_xy(
				'Document Title', 20, $this->getUpperRightY() + 10
			);
			
			// Add the page number to each page added
			$this->getObj()->setfont(
				$this->getNormalFontNumber(), $this->getFontSize()
			);
			$this->getObj()->show_xy(
				"Page $page", $this->getUpperRightX(), 20
			);
			$page++;

			// Fit the table data onto the current page
			$optlist = 'header=1 fill={{area=rowodd fillcolor='
				. '{gray 0.9}}} stroke={{line=other}} ';
			$result = $this->getObj()->fit_table(
				$table_ref, 
				$this->getLowerLeftX(), 
				$this->getLowerLeftY(), 
				$this->getUpperRightX(), 
				$this->getUpperRightY(), 
				$optlist
			);
			if ($result ==  '_error') {
				die('Couldn\'t place table: ' 
					. $this->getObj()->get_errmsg());
			}

			$this->getObj()->end_page_ext('');

		} while ($result == '_boxfull');

		if ($result != '_stop')
		{
			if ($result ==  '_error')
			{
				die('Error when placing table: ' 
					. $this->getObj()->get_errmsg());
			}
			else
			{
				die('User return found in Textflow');
			}
		}

		$this->getObj()->delete_table($table_ref, '');
		$this->getObj()->end_document('');
	}
}
?>
